package no.rmz.chez.evaluators;

import no.rmz.chez.chess.board.ChessBoard;
import no.rmz.chez.chess.board.Color;
import no.rmz.chez.chess.pieces.ChessPiece;


/**
 * A heuristic for determining when a board is
 * final, and when it's not, if it's good or
 * bad for a player with a particular color.
 */
public abstract  class BoardEvaluator {
    /**
     * Representing positive infinity with the largest possible
     * integer value.
     */
    public static final  double POS_INFTY = Double.MAX_VALUE;
    /**
     * Representing negative infinity with the smallest possible
     * integer value.
     */
    public static final  double NEG_INFTY = -POS_INFTY;

    /**
     * Return an integer value that will describe the goodness
     * of the chessboard, as seen from the perspective of a player
     * of a particuar color.
     * @param b The chessboard
     * @param c The color of the player.
     * @return The goodness.  +infty is winning +infty is losing, everythihg
     *         in between is heuristic evaluations of the position. Higher
     *         values are better than lower ones.
     */
    public abstract double evaluate(ChessBoard b, Color c);

    /**
     * Return true iff the chessboard is in a terminal
     * position, i.e. it is not possible to produce more moves
     * with this board as a basis.
     *
     * @param b the board
     * @return true iff it is impossible to play more.
     */
    public final boolean  isTerminal(final ChessBoard b) {
        return !b.hasTwoKings();
    }

    /**
     * Assuming that a game is terminated, figure out who won,
     * returning the color of the winner.
     * @param b  the board to test.
     * @return the color of the winning player.
     */
    public final Color getWinningColor(final ChessBoard b) {
        assert (isTerminal(b));
        if (b.getPieces().contains(ChessPiece.WK)) {
            return Color.WHITE;
        } else {
            return Color.BLACK;
        }
    }
}